#include "../../../Include/DataType/Graph/WizDataTypeGraph.hpp"
#include "../../../Include/DataType/Graph/WizDataTypeGraphNode.hpp"
#include "../../../Include/DataType/Graph/WizDataTypeGraphLink.hpp"

namespace Wiz
{
    namespace DGraph
    {
        namespace Link
        {
            Type::Type(::Wiz::DGraph::Node::Ptr Owner, ::Wiz::DGraph::Link::eIOType IO, ::Wiz::Size::In MaxSize) : m_Owner(Owner), m_IOType(IO), m_MaxSize(MaxSize)
            {
            }

            Type::~Type()
            {
                this->Clear();
            }

            ::Wiz::Bool::Type Type::Connect(::Wiz::DGraph::Link::Ptr LinkPtr)
            {
                WIZ_ASSERT(LinkPtr != WIZ_NULL);
                /// Input can NOT connect Input, and so on Output can NOT connect Output;
                if (LinkPtr->m_IOType == this->m_IOType)
                {
                    return ::Wiz::Bool::False;
                }

                if ((this->m_Links.Size() <= this->m_MaxSize) || (LinkPtr->m_Links.Size() <= LinkPtr->m_MaxSize))
                {
                    return ::Wiz::Bool::False;
                }

                this->m_Links.Insert(LinkPtr);
                LinkPtr->m_Links.Insert(this);

                return ::Wiz::Bool::True;
            }

            ::Wiz::Void::Type Type::Break(::Wiz::DGraph::Link::Ptr LinkPtr)
            {
                WIZ_ASSERT(LinkPtr != WIZ_NULL);
                /// Input can NOT connect Input, and so on Output can NOT connect Output;
                WIZ_ASSERT(LinkPtr->m_IOType != this->m_IOType);

                ::Wiz::DGraph::Link::Set::Iterator OutItr = this->m_Links.Find(LinkPtr);
                if (OutItr != this->m_Links.End())
                {
                    this->m_Links.Erase(OutItr);
                }

                ::Wiz::DGraph::Link::Set::Iterator InItr = LinkPtr->m_Links.Find(this);
                if (InItr != LinkPtr->m_Links.End())
                {
                    LinkPtr->m_Links.Erase(InItr);
                }
            }

            ::Wiz::Void::Type Type::Clear()
            {
                ::Wiz::DGraph::Link::Set::ConstIterator Curr;
                ::Wiz::DGraph::Link::Set::ConstForEach FE(Curr, this->m_Links);

                while (FE.HasMoreElement())
                {
                    ::Wiz::DGraph::Link::Set::Iterator Itr = (*Curr)->m_Links.Find(this);
                    if (Itr != (*Curr)->m_Links.End())
                    {
                        (*Curr)->m_Links.Erase(Itr);
                    }
                }

                this->m_Links.Clear();
            }

            namespace Input
            {
                Type::Type(::Wiz::DGraph::Node::Ptr Owner, ::Wiz::Size::Type MaxSize/*= 1*/) : Super(Owner, ::Wiz::DGraph::Link::eInput, MaxSize)
                {
                }
                Type::~Type()
                {
                }
            } /// end of namespace Input

            namespace Output
            {
                Type::Type(::Wiz::DGraph::Node::Ptr Owner, ::Wiz::Size::Type MaxSize/*= ::Wiz::Size::Max*/) : Super(Owner, ::Wiz::DGraph::Link::eOutput, MaxSize)
                {
                }
                Type::~Type()
                {
                }
            } /// end of namespace Output
        } /// end of namespace Link
    } /// end of namespace DGraph
} /// end of namespace Wiz
